package com.baizhi.shane.shane.service.impl;

import com.baizhi.shane.common.base.Result;
import com.baizhi.shane.constant.SysMapping;
import com.baizhi.shane.enums.ResultCode;
import com.baizhi.shane.shane.dto.*;
import com.baizhi.shane.shane.entity.ShaneQuestion;
import com.baizhi.shane.shane.manager.CountVOManager;
import com.baizhi.shane.shane.vo.*;
import com.baizhi.shane.sys.manager.RedisManager;
import com.baizhi.shane.sys.service.SysUserService;
import com.baizhi.shane.sys.utils.CommonUtils;
import com.baizhi.shane.sys.vo.IdVO;
import com.baizhi.shane.sys.vo.LoginUserVO;
import com.baizhi.shane.sys.vo.SuccessedOutVO;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.baizhi.shane.shane.entity.ShaneEssay;
import com.baizhi.shane.shane.service.ShaneEssayService;
import com.baizhi.shane.shane.mapper.ShaneEssayMapper;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
* @author wbz12
* @description 针对表【shane_essay(啥呢文章表)】的数据库操作Service实现
* @createDate 2023-07-25 22:33:37
*/
@Service
public class ShaneEssayServiceImpl extends ServiceImpl<ShaneEssayMapper, ShaneEssay>
    implements ShaneEssayService{

    @Resource
    private CommonUtils commonUtils;
    @Resource
    private ShaneEssayMapper shaneEssayMapper;
    @Resource
    private SysUserService sysUserService;
    @Resource
    private RedisManager redisManager;
    @Resource
    private CountVOManager countVOManager;
    
    /**
     * 通过关键字模糊查询文章列表
     *
     * @Author 闻柏智
     * @Date 16:19 2024/3/2
     * @Param pageInVO
     * @return java.util.List<com.baizhi.shane.shane.vo.PageEssayOutVO>
     **/
    @Override
    public List<PageEssayOutVO> pageByContent(PageInVO pageInVO) {
        // 转查询DTO
        PageInDTO pageInDTO = commonUtils.pageInVOToDTO(pageInVO, null);
        // 获取查询结果
        List<PageEssayOutDTO> pageEssayOutDTOList = shaneEssayMapper.pageByContent(pageInDTO);
        /* 无数据则返回空数组 */
        if (CollectionUtils.isEmpty(pageEssayOutDTOList)) {
            return new ArrayList<>();
        }
        // 初始化返回值
        List<PageEssayOutVO> pageEssayOutVOList = new ArrayList<>();
        // 提取问题ID列表
        List<Long> essayIdList = pageEssayOutDTOList
                .stream()
                .map(PageEssayOutDTO::getEssayId)
                .collect(Collectors.toList());
        /* 获取关系集合 */
        Map<Long, CountVO> likeMap = this.getEssayLikeCountMapByEssayIdList(essayIdList);
        Map<Long, CountVO> againstMap = this.getEssayAgainstCountMapByEssayIdList(essayIdList);
        Map<Long, CountVO> collectMap = this.getEssayCollectCountMapByEssayIdList(essayIdList);
        Map<Long, CountVO> commentMap = this.getEssayCommentCountMapByEssayIdList(essayIdList);
        /* 构建返回对象 */
        for (PageEssayOutDTO pageEssayOutDTO : pageEssayOutDTOList) {
            PageEssayOutVO pageEssayOutVO = this.pageDTOToVO(pageEssayOutDTO, likeMap, againstMap, collectMap, commentMap);

            pageEssayOutVOList.add(pageEssayOutVO);
        }

        return pageEssayOutVOList;
    }

    /**
     * 分页查询问题列表的DTO转VO
     *
     * @Author 闻柏智
     * @Date 21:23 2024/1/25
     * @Param pageEssayOutDTO
     * @Param likeMap:
     * @Param againstMap:
     * @Param collectMap:
     * @Param commentMap:
     * @return com.baizhi.shane.shane.vo.PageEssayOutVO
     **/
    private PageEssayOutVO pageDTOToVO (
            PageEssayOutDTO pageEssayOutDTO,
            Map<Long, CountVO> likeMap,
            Map<Long, CountVO> againstMap,
            Map<Long, CountVO> collectMap,
            Map<Long, CountVO> commentMap
    ) {
        PageEssayOutVO pageEssayOutVO = new PageEssayOutVO();
        // 复制值
        BeanUtils.copyProperties(pageEssayOutDTO,pageEssayOutVO);
        // 默认评论树不显示
        pageEssayOutVO.setShowComment(SysMapping.NOT_DISPLAY_COMMENT_TREE);
        /* 评论树空数组 */
        pageEssayOutVO.setCommentTreeList(new ArrayList<>());
        /* 展示内容结尾加省略号 */
        String newDisplayText = pageEssayOutDTO.getEssayDisplayText() + SysMapping.ELLIPSIS;
        pageEssayOutVO.setEssayDisplayText(newDisplayText);
        /* 补充关系 */
        Long essayId = pageEssayOutVO.getEssayId();
        pageEssayOutVO.setLikeCount(likeMap.get(essayId).getTheCount().longValue());
        pageEssayOutVO.setNowUserLiked(likeMap.get(essayId).getNowUserRelIt());
        pageEssayOutVO.setNowUserLikedRelId(likeMap.get(essayId).getNowUserRelIt());

        pageEssayOutVO.setAgainstCount(againstMap.get(essayId).getTheCount().longValue());
        pageEssayOutVO.setNowUserAgainsted(againstMap.get(essayId).getNowUserRelIt());
        pageEssayOutVO.setNowUserAgainstRelId(againstMap.get(essayId).getNowUserRelIt());

        pageEssayOutVO.setCollectCount(collectMap.get(essayId).getTheCount().longValue());
        pageEssayOutVO.setNowUserCollected(collectMap.get(essayId).getNowUserRelIt());
        pageEssayOutVO.setNowUserCollectedRelId(collectMap.get(essayId).getNowUserRelIt());

        pageEssayOutVO.setCommentCount(commentMap.get(essayId).getTheCount().longValue());
        pageEssayOutVO.setNowUserCommented(commentMap.get(essayId).getNowUserRelIt());
        pageEssayOutVO.setNowUserCollectedRelId(commentMap.get(essayId).getNowUserRelIt());

        // 默认不展示评论树
        pageEssayOutVO.setShowComment(0l);
        return pageEssayOutVO;

    }

    /**
     * 通过文章ID列表查询这些文章的点赞数量
     *
     * @Author 闻柏智
     * @Date 20:29 2024/1/21
     * @Param essayIdList
     * @return java.util.List<com.baizhi.shane.shane.vo.CountVO>
     **/
    @Override
    public List<CountVO> getEssayLikeCountByEssayIdList(List<Long> essayIdList) {
        Long userId = this.redisManager.getUserId();
        List<CountVO> countVOList = this.shaneEssayMapper.getEssayLikeCountByEssayIdList(essayIdList, userId);
        return countVOList;
    }

    /**
     * 通过文章ID查询单个文章的点赞数量
     *
     * @Author 闻柏智
     * @Date 20:35 2024/1/21
     * @Param essayId
     * @return com.baizhi.shane.shane.vo.CountVO
     **/
    @Override
    public CountVO getOneEssayLikeCountByEssayId(Long essayId) {
        List<Long> essayIdList = new ArrayList<Long>() {{
            add(essayId);
        }};
        List<CountVO> countVOList = this.getEssayLikeCountByEssayIdList(essayIdList);
        CountVO countVO = countVOManager.countVOListToOneVO(countVOList, essayId);
        return countVO;
    }

    /**
     * 通过文章ID查询单个文章的点赞数量，并且转化成Map
     *
     * @Author 闻柏智
     * @Date 20:40 2024/1/21
     * @Param essayIdList
     * @return java.util.Map<java.lang.Long,com.baizhi.shane.shane.vo.CountVO>
     **/
    @Override
    public Map<Long, CountVO> getEssayLikeCountMapByEssayIdList(List<Long> essayIdList) {
        List<CountVO> essayLikeCountByEssayIdList = this.getEssayLikeCountByEssayIdList(essayIdList);
        Map<Long, CountVO> likeMap = essayLikeCountByEssayIdList
                .stream()
                .collect(Collectors.toMap(
                        CountVO::getEntityId, // Key属性
                        Function.identity()  // Value属性
                ));

        return likeMap;
    }

    /**
     * 通过文章ID列表查询这些文章的反对数量
     *
     * @Author 闻柏智
     * @Date 21:01 2024/1/21
     * @Param essayIdList
     * @return java.util.List<com.baizhi.shane.shane.vo.CountVO>
     **/
    @Override
    public List<CountVO> getEssayAgainstCountByEssayIdList(List<Long> essayIdList) {
        Long userId = this.redisManager.getUserId();
        List<CountVO> countVOList = this.shaneEssayMapper.getEssayAgainstCountByEssayIdList(essayIdList, userId);
        return countVOList;
    }

    /**
     * 通过文章ID查询单个文章的反对数量
     *
     * @Author 闻柏智
     * @Date 21:03 2024/1/21
     * @Param essayId
     * @return com.baizhi.shane.shane.vo.CountVO
     **/
    @Override
    public CountVO getOneEssayAgainstCountByEssayId(Long essayId) {
        List<Long> essayIdList = new ArrayList<Long>() {{
            add(essayId);
        }};
        List<CountVO> countVOList = this.getEssayAgainstCountByEssayIdList(essayIdList);
        CountVO countVO = countVOManager.countVOListToOneVO(countVOList, essayId);
        return countVO;
    }

    /**
     * 通过文章ID列表查询这些文章的点赞数量，并且转化为Map
     *
     * @Author 闻柏智
     * @Date 21:05 2024/1/21
     * @Param essayIdList
     * @return java.util.Map<java.lang.Long,com.baizhi.shane.shane.vo.CountVO>
     **/
    @Override
    public Map<Long, CountVO> getEssayAgainstCountMapByEssayIdList(List<Long> essayIdList) {
        List<CountVO> essayMapCountByEssayIdList = this.getEssayAgainstCountByEssayIdList(essayIdList);
        Map<Long, CountVO> againstMap = essayMapCountByEssayIdList
                .stream()
                .collect(Collectors.toMap(
                        CountVO::getEntityId, // Key属性
                        Function.identity()  // Value属性
                ));

        return againstMap;
    }

    /**
     * 通过文章ID列表查询这些文章的收藏数量
     *
     * @Author 闻柏智
     * @Date 15:27 2024/1/22
     * @Param essayIdList
     * @return java.util.List<com.baizhi.shane.shane.vo.CountVO>
     **/
    @Override
    public List<CountVO> getEssayCollectCountByEssayIdList(List<Long> essayIdList) {
        Long userId = this.redisManager.getUserId();
        List<CountVO> countVOList = this.shaneEssayMapper.getEssayCollectCountByEssayIdList(essayIdList, userId);
        return countVOList;
    }

    /**
     * 通过文章ID列表查询这些文章的收藏数量，并且转为Map
     *
     * @Author 闻柏智
     * @Date 15:30 2024/1/22
     * @Param essayIdList
     * @return java.util.Map<java.lang.Long,com.baizhi.shane.shane.vo.CountVO>
     **/
    @Override
    public Map<Long, CountVO> getEssayCollectCountMapByEssayIdList(List<Long> essayIdList) {
        List<CountVO> essayMapCountByEssayIdList = this.getEssayCollectCountByEssayIdList(essayIdList);
        Map<Long, CountVO> collectMap = essayMapCountByEssayIdList
                .stream()
                .collect(Collectors.toMap(
                        CountVO::getEntityId, // Key属性
                        Function.identity()  // Value属性
                ));
        return collectMap;
    }

    /**
     * 通过文章ID查询单个文章的收藏数量
     *
     * @Author 闻柏智
     * @Date 15:33 2024/1/22
     * @Param essayId
     * @return com.baizhi.shane.shane.vo.CountVO
     **/
    @Override
    public CountVO getOneEssayCollectCountByEssayId(Long essayId) {
        List<Long> essayIdList = new ArrayList<Long>() {{
            add(essayId);
        }};
        List<CountVO> countVOList = this.getEssayCollectCountByEssayIdList(essayIdList);
        CountVO countVO = countVOManager.countVOListToOneVO(countVOList, essayId);
        return countVO;
    }

    /**
     * 通过文章ID列表查询这些文章的评论数量
     *
     * @Author 闻柏智
     * @Date 15:37 2024/1/22
     * @Param essayIdList
     * @return java.util.List<com.baizhi.shane.shane.vo.CountVO>
     **/
    @Override
    public List<CountVO> getEssayCommentCountByEssayIdList(List<Long> essayIdList) {
        Long userId = this.redisManager.getUserId();
        List<CountVO> countVOList = this.shaneEssayMapper.getEssayCommentCountByEssayIdList(essayIdList, userId);
        return countVOList;
    }

    /**
     * 通过文章ID列表查询这些文章的评论数量
     *
     * @Author 闻柏智
     * @Date 15:39 2024/1/22
     * @Param essayIdList
     * @return java.util.Map<java.lang.Long,com.baizhi.shane.shane.vo.CountVO>
     **/
    @Override
    public Map<Long, CountVO> getEssayCommentCountMapByEssayIdList(List<Long> essayIdList) {
        List<CountVO> essayMapCountByEssayIdList = this.getEssayCommentCountByEssayIdList(essayIdList);
        Map<Long, CountVO> commentMap = essayMapCountByEssayIdList
                .stream()
                .collect(Collectors.toMap(
                        CountVO::getEntityId, // Key属性
                        Function.identity()  // Value属性
                ));
        return commentMap;
    }

    /**
     * 通过文章ID列表查询这些文章的评论数量
     *
     * @Author 闻柏智
     * @Date 15:41 2024/1/22
     * @Param essayId
     * @return com.baizhi.shane.shane.vo.CountVO
     **/
    @Override
    public CountVO getOneEssayCommentCountByEssayId(Long essayId) {
        List<Long> essayIdList = new ArrayList<Long>() {{
            add(essayId);
        }};
        List<CountVO> countVOList = this.getEssayCommentCountByEssayIdList(essayIdList);
        CountVO countVO = countVOManager.countVOListToOneVO(countVOList, essayId);
        return countVO;
    }

    /**
     * 通过ID查询单个文章信息
     *
     * @Author 闻柏智
     * @Date 16:21 2024/2/29
     * @Param essayId
     * @return com.baizhi.shane.shane.vo.GetOneEssayOutVO
     **/
    @Override
    public GetOneEssayOutVO getOneEssayById(Long essayId) {

        // 查询
        GetOneEssayOutDTO getOneEssayOutDTO = this.shaneEssayMapper.getOneEssayById(essayId);
        // 初始化返回值
        GetOneEssayOutVO getOneEssayOutVO = new GetOneEssayOutVO();
        // 复制属性
        BeanUtils.copyProperties(getOneEssayOutDTO, getOneEssayOutVO);

        /* 获取关系 */
        CountVO likeVO = this.getOneEssayLikeCountByEssayId(essayId);
        CountVO collectVO = this.getOneEssayCollectCountByEssayId(essayId);
        CountVO commentVO = this.getOneEssayCommentCountByEssayId(essayId);

        /* 赋值关系值 */
        getOneEssayOutVO.setLikeCount(likeVO.getTheCount().longValue());
        getOneEssayOutVO.setCollectCount(collectVO.getTheCount().longValue());
        getOneEssayOutVO.setCommentCount(commentVO.getTheCount().longValue());
        getOneEssayOutVO.setNowUserLiked(likeVO.getNowUserRelIt());
        getOneEssayOutVO.setNowUserCollected(collectVO.getNowUserRelIt());
        getOneEssayOutVO.setNowUserCommented(commentVO.getNowUserRelIt());
        getOneEssayOutVO.setNowUserLikedRelId(likeVO.getNowUserRelId());
        getOneEssayOutVO.setNowUserCollectedRelId(collectVO.getNowUserRelId());

        // 评论树默认不显示
        getOneEssayOutVO.setShowComment(0l);

        return getOneEssayOutVO;
        
    }

    /**
     * 新增一个文章
     *
     * @Author 闻柏智
     * @Date 16:27 2024/3/2
     * @Param essayInsertInVO
     * @return com.baizhi.shane.sys.vo.SuccessedOutVO
     **/
    @Override
    public SuccessedOutVO insertOne(EssayInsertInVO essayInsertInVO) {

        if (essayInsertInVO == null) {
            Result.fail(ResultCode.PARAM_IS_INVALID);
        }
        ShaneEssay shaneEssay = new ShaneEssay();
        BeanUtils.copyProperties(essayInsertInVO, shaneEssay);

        shaneEssay.setDisplayText(StringUtils.substring(shaneEssay.getPlainText(), 0, 100));
        shaneEssay.setUserId(redisManager.getUserId());
        if (shaneEssay.getStatus() == null) {
            shaneEssay.setStatus(SysMapping.STATUS_PUBLISHED);
        }

        boolean successed = this.save(shaneEssay);
        SuccessedOutVO successedOutVO =
                commonUtils.boolToSuccessedOutVO(successed, SysMapping.INSERT_ESSAY_SUCCESS, SysMapping.INSERT_ESSAY_FAIL);

        return successedOutVO;
        
    }

    /**
     * 我发布过的文章
     *
     * @Author 闻柏智
     * @Date 21:35 2024/3/3
     * @Param
     * @return java.util.List<com.baizhi.shane.shane.entity.ShaneEssay>
     **/
    @Override
    public List<ShaneEssay> myPosted() {

        // 获取当前登陆人ID
        Long userId = redisManager.getUserId();
        /* 获取所有的文章 */
        List<ShaneEssay> shaneEssayList = this.lambdaQuery()
                .eq(ShaneEssay::getDelFlag, 0)
                .eq(ShaneEssay::getUserId, userId)
                .list();
        return shaneEssayList;
        
    }

    /**
     * 通过ID编辑文章
     *
     * @Author 闻柏智
     * @Date 22:44 2024/3/3
     * @Param shaneEssay
     * @return com.baizhi.shane.sys.vo.SuccessedOutVO
     **/
    @Override
    public SuccessedOutVO updateOneById(ShaneEssay shaneEssay) {
        shaneEssay.setDisplayText(StringUtils.substring(shaneEssay.getPlainText(), 0, 100));
        boolean successed = this.updateById(shaneEssay);
        SuccessedOutVO successedOutVO =
                commonUtils.boolToSuccessedOutVO(successed, SysMapping.CHANGE_SUCCESS, SysMapping.CHANGE_FAIL);
        return successedOutVO;
    }

    /**
     * 我收藏的文章
     *
     * @Author 闻柏智
     * @Date 14:36 2024/3/4
     * @Param
     * @return java.util.List<com.baizhi.shane.shane.entity.ShaneEssay>
     **/
    @Override
    public List<ShaneEssay> myCollected() {
        // 获取当前登陆人ID
        Long userId = redisManager.getUserId();
        List<ShaneEssay> shaneEssayList = shaneEssayMapper.myCollected(userId);
        return shaneEssayList;
    }

    /**
     * 通过文章ID列表查询这些文章的标签列表
     *
     * @Author 闻柏智
     * @Date 15:42 2024/3/4
     * @Param idListStr
     * @return java.util.List<com.baizhi.shane.shane.vo.EssayLabelOutVO>
     **/
    @Override
    public List<EssayLabelOutVO> getEssayLabelListByEssayIdList(String idListStr) {
        // 入参字符串转为Long列表
        List<Long> essayIdList = commonUtils.idListStrToLongList(idListStr);
        // 从数据库查数据
        List<EssayLabelOutDTO> essayLabelOutDTOList =
                this.shaneEssayMapper.getEssayLabelListByEssayIdList(essayIdList);
        /* 按照问题ID分组 */
        Map<Long, List<EssayLabelOutDTO>> idEntityMap = essayLabelOutDTOList
                .stream()
                .collect(Collectors.groupingBy(EssayLabelOutDTO::getEssayId));
        // 提取问题ID集合
        Set<Long> essayIdSet = idEntityMap.keySet();
        // 创建VO列表
        List<EssayLabelOutVO> essayLabelOutVOList = new ArrayList<>();
        /* 构建返回值列表 */
        for (Long essayId : essayIdSet) {
            EssayLabelOutVO essayLabelOutVO = new EssayLabelOutVO();
            essayLabelOutVO.setEssayLabelOutDTOList(new ArrayList<>());
            List<EssayLabelOutDTO> labelList = idEntityMap.get(essayId);
            essayLabelOutVO.setEssayId(essayId);
            if (!CollectionUtils.isEmpty(labelList)) {
                essayLabelOutVO.setEssayLabelOutDTOList(labelList);
            }
            essayLabelOutVOList.add(essayLabelOutVO);

        }
        return essayLabelOutVOList;
    }

    /**
     * 通过文章ID查询单个文章的标签
     *
     * @Author 闻柏智
     * @Date 15:44 2024/3/4
     * @Param essayId
     * @return com.baizhi.shane.shane.vo.EssayLabelOutVO
     **/
    @Override
    public EssayLabelOutVO getEssayLabelByEssayId(Long essayId) {
        String idListStr = essayId.toString() + SysMapping.COMMA;
        List<EssayLabelOutVO> essayLabelOutVOList = this.getEssayLabelListByEssayIdList(idListStr);
        if (CollectionUtils.isEmpty(essayLabelOutVOList)) {
            return new EssayLabelOutVO();
        }
        EssayLabelOutVO essayLabelOutVO = essayLabelOutVOList.get(0);
        return essayLabelOutVO;
    }

    /**
     * 通过关键字查询文章列表的元素数量和分页个数
     *
     * @Author 闻柏智
     * @Date 16:01 2024/3/4
     * @Param pageInVO
     * @return com.baizhi.shane.shane.vo.CountAndPageOutVO
     **/
    @Override
    public CountAndPageOutVO countAndPageByContent(PageInVO pageInVO) {
        String content = pageInVO.getContent();
        Integer pageSize = pageInVO.getPageSize();
        if (pageSize == null) {
            pageSize = 10;
        }
        double pageSizeDouble = pageSize.doubleValue();
        Integer count = this.shaneEssayMapper.countAndPageByContent(content);

        int pageCountInt = (int) Math.ceil(count / pageSizeDouble);
        Integer pageCount = pageCountInt;

        CountAndPageOutVO countAndPageOutVO = new CountAndPageOutVO();
        countAndPageOutVO.setMaxCount(count);
        countAndPageOutVO.setPageCount(pageCount);

        return countAndPageOutVO;
    }

    /**
     * 删除一个文章-通过ID
     *
     * @Author 闻柏智
     * @Date 16:15 2024/3/4
     * @Param idVO
     * @return com.baizhi.shane.sys.vo.SuccessedOutVO
     **/
    @Override
    public SuccessedOutVO deleteOneEssayById(IdVO idVO) {
        Long id = idVO.getId();
        boolean success = this.removeById(id);
        SuccessedOutVO successedOutVO = commonUtils.boolToSuccessedOutVO(success, null, null);
        return successedOutVO;
    }
}




